package com.ics.atable.chat.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ics.atable.chat.expection.BusinessException;
import com.ics.atable.chat.model.dto.SqlReplaceDTO;
import com.ics.atable.chat.service.SqlQueryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;

import java.util.HashMap;
import java.util.Map;

/**
 * SQL 查询 API
 *
 * @author system
 */
@Slf4j
@RestController
@RequestMapping("/sql-replace")
@Tag(name = "SQL查询接口", description = "提供数据查询功能")
public class SqlReplaceController {

    @Autowired
    private SqlQueryService sqlQueryService;

    /**
     * 同步查询接口
     *
     * @param request 查询请求
     * @return 查询结果
     */
    @PostMapping("/run")
    @Operation(
        summary = "同步查询数据", 
        description = "根据查询条件同步查询数据库并返回结果。" +
                      "查询条件包括：指标全量名称、填报列全量名称、年份、季度、区划名。" +
                      "返回结果包含查询到的所有数据行，每行包含完整的字段信息。"
    )
    public Map<String, Object> run(@RequestBody @Valid SqlReplaceDTO.QueryRequest request) {
        try {
            log.info("收到查询请求: {}", request.getReplace());
            
            SqlReplaceDTO.QueryResponse response = sqlQueryService.queryData(request.getReplace());

            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("data", response.getResults());
            result.put("count", response.getCount());
            result.put("explanation", response.getExplanation());
            
            log.info("查询成功，返回 {} 条记录", response.getCount());
            return result;

        } catch (BusinessException e) {
            log.error("查询失败: {}", e.getMessage());
            Map<String, Object> errorResp = new HashMap<>();
            errorResp.put("success", false);
            errorResp.put("error", e.getMessage());
            return errorResp;
        } catch (Exception e) {
            log.error("系统错误", e);
            Map<String, Object> errorResp = new HashMap<>();
            errorResp.put("success", false);
            errorResp.put("error", "系统错误: " + e.getMessage());
            return errorResp;
        }
    }

    /**
     * 流式查询接口
     *
     * @param request 查询请求
     * @return SSE 流式响应
     */
    @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(
        summary = "流式查询数据", 
        description = "根据查询条件流式查询数据库并返回结果。" +
                      "使用 Server-Sent Events (SSE) 格式返回数据。" +
                      "成功时返回 stage='done' 和数据，失败时返回 stage='error' 和错误信息。"
    )
    public Flux<ServerSentEvent<String>> stream(@RequestBody @Valid SqlReplaceDTO.QueryRequest request) {
        Sinks.Many<ServerSentEvent<String>> sink = Sinks.many().unicast().onBackpressureBuffer();

        try {
            log.info("收到流式查询请求: {}", request.getReplace());
            
            SqlReplaceDTO.QueryResponse response = sqlQueryService.queryData(request.getReplace());

            // 转换为 JSON
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonResult = objectMapper.writeValueAsString(response.getResults());
            String explanationJson = objectMapper.writeValueAsString(response.getExplanation());

            String payload = String.format("{\"stage\":\"done\",\"data\":%s,\"count\":%d,\"explanation\":%s}",
                    jsonResult, response.getCount(), explanationJson);
            sink.tryEmitNext(ServerSentEvent.builder(payload).build());
            sink.tryEmitComplete();
            
            log.info("流式查询成功，返回 {} 条记录", response.getCount());

        } catch (BusinessException e) {
            log.error("查询失败: {}", e.getMessage());
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString(e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        } catch (JsonProcessingException e) {
            log.error("JSON 序列化失败", e);
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString("数据序列化失败: " + e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        } catch (Exception e) {
            log.error("系统错误", e);
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString("系统错误: " + e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        }

        return sink.asFlux()
                .doOnCancel(() -> log.info("客户端断开连接"))
                .doOnError(e -> log.error("流式响应错误", e));
    }

    /**
     * 批量查询接口
     *
     * @param request 批量查询请求
     * @return 查询结果
     */
    @PostMapping("/batch-run")
    @Operation(
        summary = "批量查询数据", 
        description = "根据多个地区名称批量查询数据库并返回结果。" +
                      "查询条件包括：指标全量名称、填报列全量名称、年份、季度、区划名列表。" +
                      "返回结果包含查询到的所有数据行，每行包含完整的字段信息。"
    )
    public Map<String, Object> batchRun(@RequestBody @Valid SqlReplaceDTO.BatchQueryRequest request) {
        try {
            log.info("收到批量查询请求，地区数量: {}", request.getReplace().getFullOrgNames().size());
            
            SqlReplaceDTO.QueryResponse response = sqlQueryService.batchQueryData(request.getReplace());

            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("data", response.getResults());
            result.put("count", response.getCount());
            result.put("explanation", response.getExplanation());
            
            log.info("批量查询成功，返回 {} 条记录", response.getCount());
            return result;

        } catch (BusinessException e) {
            log.error("批量查询失败: {}", e.getMessage());
            Map<String, Object> errorResp = new HashMap<>();
            errorResp.put("success", false);
            errorResp.put("error", e.getMessage());
            return errorResp;
        } catch (Exception e) {
            log.error("系统错误", e);
            Map<String, Object> errorResp = new HashMap<>();
            errorResp.put("success", false);
            errorResp.put("error", "系统错误: " + e.getMessage());
            return errorResp;
        }
    }

    /**
     * 批量流式查询接口
     *
     * @param request 批量查询请求
     * @return SSE 流式响应
     */
    @PostMapping(value = "/batch-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(
        summary = "批量流式查询数据", 
        description = "根据多个地区名称批量流式查询数据库并返回结果。" +
                      "使用 Server-Sent Events (SSE) 格式返回数据。" +
                      "成功时返回 stage='done' 和数据，失败时返回 stage='error' 和错误信息。"
    )
    public Flux<ServerSentEvent<String>> batchStream(@RequestBody @Valid SqlReplaceDTO.BatchQueryRequest request) {
        Sinks.Many<ServerSentEvent<String>> sink = Sinks.many().unicast().onBackpressureBuffer();

        try {
            log.info("收到批量流式查询请求，地区数量: {}", request.getReplace().getFullOrgNames().size());
            
            SqlReplaceDTO.QueryResponse response = sqlQueryService.batchQueryData(request.getReplace());

            // 转换为 JSON
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonResult = objectMapper.writeValueAsString(response.getResults());
            String explanationJson = objectMapper.writeValueAsString(response.getExplanation());

            String payload = String.format("{\"stage\":\"done\",\"data\":%s,\"count\":%d,\"explanation\":%s}",
                    jsonResult, response.getCount(), explanationJson);
            sink.tryEmitNext(ServerSentEvent.builder(payload).build());
            sink.tryEmitComplete();
            
            log.info("批量流式查询成功，返回 {} 条记录", response.getCount());

        } catch (BusinessException e) {
            log.error("批量查询失败: {}", e.getMessage());
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString(e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        } catch (JsonProcessingException e) {
            log.error("JSON 序列化失败", e);
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString("数据序列化失败: " + e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        } catch (Exception e) {
            log.error("系统错误", e);
            String err = String.format("{\"stage\":\"error\",\"message\":%s}",
                    escapeJsonString("系统错误: " + e.getMessage()));
            sink.tryEmitNext(ServerSentEvent.builder(err).build());
            sink.tryEmitComplete();
        }

        return sink.asFlux()
                .doOnCancel(() -> log.info("客户端断开连接"))
                .doOnError(e -> log.error("流式响应错误", e));
    }

    /**
     * 转义 JSON 字符串
     *
     * @param s 字符串
     * @return 转义后的 JSON 字符串
     */
    private String escapeJsonString(String s) {
        if (s == null) {
            return "\"\"";
        }
        String esc = s.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r");
        return "\"" + esc + "\"";
    }
}
